<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        li {
            list-style: none;
        }

        .wrap {
            margin-top: 20px;
        }

        #title {
            line-height: 60px;
            font-size: 32px;
        }

        .list li {
            line-height: 40px;
            border: 1px dashed #333;
            text-indent: 10px;
        }
    </style>
</head>

<body>
    <div class="wrap">
        <h2 id="title">标题</h2>
        <ul class="list">
            <li>01</li>
            <li>02</li>
            <li>03</li>
            <li>04</li>
            <li>05</li>
            <li>06</li>
        </ul>
    </div>
    <p>
        <button class="setHtml">设置html</button>
        <button class="getHtml">获取html</button>
        <button class="hide">hide</button>
        <button class="show">show</button>
    </p>
</body>
<script>
    // DOM操作  =>  获取元素,操作元素(修改元素的内容 属性 样式 绑定事件),元素的增删改查

    // 目的: 对DOM操作进行封装,可以方便用户快捷获取元素,操作元素,以及元素的增删改查

    // 构造函数版  => 获取元素,返回获取的元素组成的集合(伪数组 -> 实例化对象)
    function GetEle(selector) { // selector 传入css选择器
        // {}
        // {}[[Prototype]] = GetEle.prototype;
        // this -> {}
        // return this;

        var list = document.querySelectorAll(selector);  // 对应选择器获取元素 (伪数组)
        list = Array.from(list);  // 伪数组转真数组
        Object.setPrototypeOf(list, GetEle.prototype); // 直接修改伪数组的[[Prototype]]可能会丢失length属性 => 先转真数组,真数组改伪数组

        // 自定义构造函数的返回值
        return list; // 返回伪数组, 有数组的结构,但是又可以访问GetEle.prototype上的方法
    }

    // 根据伪数组(实例化对象) => 操作集合中的元素

    // text()  获取和设置元素内的文本结构
    // text("123123")   有参数就设置
    // text()           没有参数就获取
    GetEle.prototype.text = function (con) { // 设置元素内文本结构
        // this -> 调用此方法的实例化对象 ((实例化对象可以继续访问GetEle.prototype上的方法 ))

        // arguments => 函数的内置参数,用于存本次函数调用时实际参数的集合

        if (arguments.length >= 1) {  // 有参数
            // 设置
            // for (var i = 0; i < this.length; i++) {
            //     var ele = this[i];
            //     ele.innerText = con;
            // }

            this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
                ele.innerText = con;
            })

        } else { // 没有参数
            // 获取
            return this[0].innerText;
        }
    }

    // html()  获取和设置元素内的html结构
    // html("123123")   有参数就设置
    // html()           没有参数就获取
    GetEle.prototype.html = function (con) { // 设置元素内文本结构
        // this -> 调用此方法的实例化对象

        // arguments => 函数的内置参数,用于存本次函数调用时实际参数的集合

        if (arguments.length >= 1) {  // 有参数
            // 设置
            // for (var i = 0; i < this.length; i++) {
            //     var ele = this[i];
            //     ele.innerHTML = con;
            // }

            this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
                ele.innerHTML = con;
            })

        } else { // 没有参数
            // 获取
            return this[0].innerHTML;
        }
    }


    // val()  获取和设置元素内的value值
    // val("123123")   有参数就设置
    // val()           没有参数就获取
    GetEle.prototype.val = function (con) { // 设置元素内文本结构
        // this -> 调用此方法的实例化对象

        // arguments => 函数的内置参数,用于存本次函数调用时实际参数的集合

        if (arguments.length >= 1) {  // 有参数
            // 设置
            // for (var i = 0; i < this.length; i++) {
            //     var ele = this[i];
            //     ele.value = con;
            // }

            this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
                ele.value = con;
            })

        } else { // 没有参数
            // 获取
            return this[0].value;
        }
    }


    // hide()  隐藏元素
    // show()  显示元素

    GetEle.prototype.hide = function () {
        // this -> 调用此方法的实例化对象
        // for (var i = 0; i < this.length; i++) {
        //     var ele = this[i];
        //     ele.style.display = "none";
        // }

        this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
            ele.style.display = "none";
        })
    }

    GetEle.prototype.show = function () {
        // this -> 调用此方法的实例化对象
        // for (var i = 0; i < this.length; i++) {
        //     var ele = this[i];
        //     ele.style.display = "block";
        // }
        this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
            ele.style.display = "block";
        })
    }



    GetEle.prototype.on = function (type, callback) {
        // this -> 调用此方法的实例化对象
        // for (var i = 0; i < this.length; i++) {
        //     var ele = this[i];
        //     ele.addEventListener(type, callback);
        // }
        this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
            ele.addEventListener(type, callback);
        })
    }

    // 对应事件类型  对on方法进行二次封装
    GetEle.prototype.click = function (callback) {
        console.log(1111, this);
        // this -> 调用此方法的实例化对象 (实例化对象可以继续访问GetEle.prototype上的方法 )
        this.on("click", callback);
    }

    GetEle.prototype.dblclick = function (callback) {
        // this -> 调用此方法的实例化对象 (实例化对象可以继续访问GetEle.prototype上的方法 )
        this.on("dblclick", callback);
    }

    GetEle.prototype.mousedown = function (callback) {
        // this -> 调用此方法的实例化对象 (实例化对象可以继续访问GetEle.prototype上的方法 )
        this.on("mousedown", callback);
    }

    // ....



    GetEle.prototype.off = function (type, callback) {
        // this -> 调用此方法的实例化对象
        // for (var i = 0; i < this.length; i++) {
        //     var ele = this[i];
        //     ele.removeEventListener(type, callback);
        // }
        this.each((ele, index) => {  // 遍历实例化对象(伪数组)  => 取出每个元素和下标
            ele.removeEventListener(type, callback);
        })
    }

    GetEle.prototype.each = function (callback) {
        // this -> 调用此方法的实例化对象 (伪数组)
        for (var i = 0; i < this.length; i++) {
            callback(this[i], i, this);
        }
    }

    function $(selector) {  // 调用$()方法 => 快速获取元素,返回元素的集合(实例化对象)
        return new GetEle(selector);
    }

    // var lis = new GetEle(".list li");
    // console.log(lis);
    // lis.text(1111);


    // var titles = new GetEle("#title");
    // console.log(titles);
    // titles.text("22222")


    // 去除中间变量
    // new GetEle(".list li").text("11111");
    // new GetEle("#title").text("222222");

    // $()  快捷获取元素版
    // $(".list li").text("11111");
    // $("#title").text("222222");

    console.log($(".list li"));
    console.log($("#title"));
    console.log($(".wrap"));


    $(".setHtml").click(function () {
        $(".list li").text("123123");
    })

    $(".getHtml").click(function () {
        alert($(".list li").text());
    })

    $(".hide").click(function () {
        $(".list li").hide();
    })

    $(".show").click(function () {
        $(".list li").show();
    })








</script>

</html>